<?php

namespace Common\Lib;


class SetupHelper
{
    /**
     * 是否空目录
     *
     * @param string $dir
     * @return bool
     */
    public function dir_is_empty($dir)
    {
        if ($handle = opendir($dir)) {
            while ($item = readdir($handle)) {
                if ($item != '.' && $item != '..') return false;
            }
        }
        return true;
    }

    /**
     * 获取文件的[存在]路径
     *
     * @param string $file
     * @return string
     */
    public function get_exists_dir($file)
    {
        $dir_name = dirname($file);
        if (file_exists($dir_name)) {
            return str_replace('\\', '/', $dir_name);
        } else {
            return $this->get_exists_dir($dir_name);
        }
    }

    /**
     * 获取更新数据文件信息
     *
     * @param string $data_dir
     * @return array|bool
     */
    public function get_data_file($data_dir)
    {
        $data_dir = realpath($data_dir);
        if (!is_dir($data_dir) || $this->dir_is_empty($data_dir)) {
            return false;
        } else {
            $files = array();
            $dir   = dir($data_dir);
            while ($file = $dir->read()) {
                if (!$this->is_special_dir($file) && is_file($data_dir . '/' . $file)) $files[] = basename($file, '.php');
            }
            $dir->close();
            return $files;
        }
    }

    /**
     * Https请求
     *
     * @param string $url
     * @param array  $data
     * @return bool|mixed
     */
    function https_request($url, $data = null)
    {
        if (function_exists('curl_init')) {
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
            if (!empty($data)) {
                curl_setopt($curl, CURLOPT_POST, 1);
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            }
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            $output = curl_exec($curl);
            curl_close($curl);
            return $output;
        } else {
            return false;
        }
    }

    /**
     * 删除目录
     *
     * @param string $dir
     * @param bool   $rm_self
     * @return bool
     */
    public function rmdirs($dir, $rm_self = false)
    {
        if (!is_dir($dir)) return false;
        $d = dir($dir);
        while (false !== ($child = $d->read())) {
            if ($child != '.' && $child != '..') {
                if (is_dir($dir . '/' . $child)) {
                    $this->rmdirs($dir . '/' . $child, true);
                } else {
                    unlink($dir . '/' . $child);
                }
            }
        }
        $d->close();
        $rm_self && rmdir($dir);
        return true;
    }


    /**
     * 解压zip文件
     *
     * @param string $data
     * @param string $path
     * @return bool|string
     */
    public function unzip($data, $path)
    {
        $zip = new \ZipArchive;
        $res = $zip->open($data);
        if ($res === true) {
            $name = basename($data, '.zip');
            $data = dirname($data);
            if (!is_dir($data)) mkdir($data, 0777, true);
            //解压缩文件夹
            $reg = $zip->extractTo($path . '/' . $name);
            $zip->close();
            return $reg ? $path . $name : false;
        } else {
            return false;
        }
    }

    /**
     * Curl获取Url内容
     *
     * @param string $url
     * @return bool|mixed|string
     */
    function get_curl($url)
    {
        if (function_exists('file_get_contents')) {
            $file_contents = file_get_contents($url);
        } else {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $file_contents = curl_exec($ch);
            curl_close($ch);
        }
        return $file_contents;
    }

    /**
     * 远程下载文件
     *
     * @param string $url  远程文件地址
     * @param string $file 保存文件名称
     * @return bool|array 保存成功返回True,失败返回False|Array
     */
    public function download_package($url, $file)
    {
        $dir = pathinfo($file, PATHINFO_DIRNAME);
        !is_dir($dir) && @mkdir($dir, 0777, true);

        $temp = $this->get_curl($url);

        $res = json_decode($temp, true);
        if (json_last_error() == JSON_ERROR_NONE) {
            return $res;
        }

        if (@file_put_contents($file, $temp)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 批量文件覆盖 [如果被覆盖文件存在，则先备份被覆盖文件]
     *
     * @param array  $cover_files
     * @param string $source_dir
     * @param string $backup_dir
     * @return bool
     */
    public function cover_files($cover_files, $source_dir, $backup_dir)
    {
        $count  = 0;
        $to_dir = realpath(APP_PATH . '..');
        foreach ($cover_files as $cover_file) {
            $form_file = "{$source_dir}{$cover_file}";
            $to_file   = "{$to_dir}{$cover_file}";
            if (file_exists($to_file)) {
                $backup_file = "{$backup_dir}/{$cover_file}";
                $this->create_dir(dirname($backup_file));
                if (!rename($to_file, $backup_file)) return $count;
            }
            $this->create_dir(dirname($to_file));
            if (!copy($form_file, $to_file)) {
                return $count;
            } else {
                $count++;
            }
        }
        return $count;
    }

    /**
     * 回滚覆盖文件
     *
     * @param array  $cover_files
     * @param string $backup_dir
     * @return bool
     */
    public function rollback_cover_files($cover_files, $backup_dir)
    {
        $to_dir = realpath(APP_PATH . '..');
        foreach ($cover_files as $cover_file) {
            $to_file = "{$to_dir}{$cover_file}";
            if (file_exists($to_file)) {
                if (!unlink($to_file)) return false;
                $backup_file = "{$backup_dir}/{$cover_file}";
                if (file_exists($backup_file)) {
                    if (!rename($backup_file, $to_file)) return false;
                }
            }
        }
        return true;
    }

    /**
     * 创建目录[不存在则创建]
     *
     * @param string $dir
     */
    public function create_dir($dir)
    {
        if (!is_dir($dir)) {
            mkdir($dir, 0777, true);
        };
    }

    /**
     * 获取目录中的所有文件名
     *
     * @param array  $arr_file
     * @param string $directory
     * @param string $dir_name
     */
    public function get_files(&$arr_file, $directory, $dir_name = '')
    {
        $dir = dir($directory);
        while ($file = $dir->read()) {
            if (!$this->is_special_dir($file)) {
                if ((is_dir("$directory/$file"))) {
                    $this->get_files($arr_file, "$directory/$file", "$dir_name/$file");
                } else {
                    $arr_file[] = "$dir_name/$file";
                }
            }
        }
        $dir->close();
    }

    /**
     * 是否特殊路径.或者..
     *
     * @param string $file
     * @return bool
     */
    private function is_special_dir($file)
    {
        return ($file == ".") || ($file == "..");
    }

    /**
     * 通过Sql文件获取sql执行语句列表
     *
     * @param string $sql_file
     * @return array
     */
    public function get_sql($sql_file)
    {
        $contents     = file_get_contents($sql_file);
        $contents     = trim(str_replace(array("\r\n", "\r"), "\n", $contents));
        $contents     = rtrim($contents, ';');
        $return_items = $items = array();
        $items        = explode(";\n", $contents);

        foreach ($items as $item) {
            $return_item = '';
            $item        = trim($item);
            $lines       = explode("\n", $item);
            foreach ($lines as $line) {
                if (isset($line[1]) && $line[0] . $line[1] == '--') {
                    continue;
                }
                $return_item .= ' ' . $line;  // add ' '
            }
            if ($return_item) {
                $return_items[] = trim($return_item); //.";";
            }
        }
        return $return_items;
    }

    /**
     * 批量删除文件
     *
     * @param array  $files
     * @param string $backup_dir
     * @return bool
     */
    public function del_files($files, $backup_dir)
    {
        $to_dir     = realpath(APP_PATH);
        $backup_dir = realpath($backup_dir);
        foreach ($files as $file) {
            $filename = $to_dir . '/' . $file;
            if (file_exists($filename)) {
                $backup_file = $backup_dir . '/' . $file;
                $this->create_dir(dirname($backup_file));
                if (!rename($filename, $backup_file)) return false;
            }
        }
        return true;
    }

    /**
     * 回滚删除文件
     *
     * @param array  $files
     * @param string $backup_dir
     * @return bool
     */
    public function backup_del_files($files, $backup_dir)
    {
        $to_dir     = realpath(APP_PATH);
        $backup_dir = realpath($backup_dir);
        foreach ($files as $file) {
            $backup_file = $backup_dir . '/' . $file;
            if (file_exists($backup_file)) {
                $to_file = $to_dir . '/' . $file;
                $this->create_dir(dirname($to_file));
                if (!rename($backup_file, $to_file)) return false;
            }
        }
        return true;
    }

    /**
     * 获取删除文件列表
     *
     * @param string $file
     * @return array|bool
     */
    public function get_del_file($file)
    {
        if (!file_exists($file) || !is_file($file)) {
            return false;
        }

        $arr_files = array();
        $f         = fopen($file, 'r');
        while (!feof($f)) {
            $file = trim(fgets($f));
            if (!empty($file)) {
                $arr_files[] = $file;
            }
        }
        fclose($f);

        return $arr_files;
    }

    /**
     * 检测文件或者目录是否全部为可读写
     *
     * @param array $check_dirs 目录(文件)的数组集合
     * @param array $ret        返回目录(文件)集合的可读写信息
     * @return bool
     */
    public function check_read_write($check_dirs, &$ret = array())
    {
        $s = true;
        foreach ($check_dirs as $key => $dir) {
            $ret[$key]['dir'] = $dir;
            if (is_readable($dir)) {
                $ret[$key]['read'] = '<span style="color:green;">√可读</span>';
            } else {
                $ret[$key]['read'] = '<span style="color:red;">×不可读</span>';
                $s                 = false;
            }
            if (is_writable($dir)) {
                $ret[$key]['write'] = '<span style="color:green;">√可写</span>';
            } else {
                $ret[$key]['write'] = '<span style="color:red;">×不可写</span>';
                $s                  = false;
            }
        }
        return $s;
    }

    /**
     * 生成配置文件
     *
     * @param string $file
     * @param array  $arr
     * @return bool|int
     */
    public function write_conf_file($file, $arr)
    {
        return file_put_contents($file, "<?php" . PHP_EOL . "return " . var_export($arr, true) . ';');
    }

    /**
     * 根据sql语法特征返回操作类型 create_table drop_table add_field chg_field drop_field insert_data
     *
     * @param        $sql
     * @param        $prefix
     * @param string $table_name
     * @return string|null
     */
    public function get_sql_act($sql, $prefix, &$table_name)
    {
        $regs = array(
            'create_table' => "/CREATE TABLE `{$prefix}([a-z0-9_]+)` .*/is",
            'drop_table'   => "/DROP TABLE IF EXISTS `{$prefix}([a-z0-9_]+)`.*/is",
            'add_field'    => "/ALTER TABLE `{$prefix}([a-z0-9_]+)` ADD COLUMN .*/is",
            'chg_field'    => "/ALTER TABLE `{$prefix}([a-z0-9_]+)` MODIFY COLUMN .*/is",
            'drop_field'   => "/ALTER TABLE `{$prefix}([a-z0-9_]+)` DROP COLUMN .*/is",
            'insert_data'  => "/INSERT INTO `{$prefix}([a-z0-9_]+)`( \(.+\))?? VALUES .*/is"
        );

        foreach ($regs as $type => $reg) {
            if (preg_match($reg, $sql)) {
                $table_name = trim(preg_replace($reg, '\\1', $sql));
                return $type;
            }
        }

        return null;
    }
}